package com.qmscy.sparrow.plugin.jwt;

import com.qmscy.sparrow.common.constant.AssertMessage;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT Token Generator<br>
 * token 的加签解签工具
 * <a>https://github.com/jwtk/jjwt</a>
 *
 * @Author: wangxiaonan
 * @Date: 2019/1/3
 **/
public class TokenGenerator {

    private static final Logger logger = LoggerFactory.getLogger(TokenGenerator.class);

    /**
     * token 签发
     * TODO 先不加权限
     *
     * @param username   用户名
     * @param isAdmin    是否是管理员
     * @param expireTime 过期时间，单位/秒
     * @param secret     加密秘钥
     * @return token
     */
    public static String sign(String username, boolean isAdmin, Long expireTime, String secret) {
        Assert.notNull(username, AssertMessage.NOT_NULL_USERNAME);
        Assert.notNull(expireTime, AssertMessage.NOT_NULL_EXPIRE);
        Assert.notNull(secret, AssertMessage.NOT_NULL_PARAM);
        logger.info("[TokenGenerator.sign] - username:{}, admin:{}, expire:{}, secret:{}", username, isAdmin, expireTime, secret);
        // header
        Map<String, Object> header = new HashMap<>();
        header.put("typ", "JWT");
        // claims
        Claims claims = Jwts.claims();
//        claims.setId(UUID.randomUUID().toString());
//        claims.setSubject("www.xx.com");
        claims.setAudience(username);
        claims.setIssuer("Sparrow-cms");
        Date now = new Date();
        claims.setIssuedAt(now);
        claims.setExpiration(new Date(now.getTime() + expireTime * 1000));
        // payload
        claims.put("adm", isAdmin);
        claims.put("rol","admin");
//        claims.put("role","")
        // secret key
        byte[] bytes = secret.getBytes();
        SecretKey secretKey = new SecretKeySpec(bytes, 0, bytes.length, SignatureAlgorithm.HS256.getJcaName());
        // sign token
        return Jwts.builder().setHeader(header).setClaims(claims).signWith(secretKey).compact();
    }

    /**
     * 解析 token
     *
     * @param token  令牌
     * @param secret 解密秘钥
     * @return body claims
     * @throws ExpiredJwtException 超时异常
     */
    public static Claims parse(String token, String secret) throws ExpiredJwtException {
        Assert.notNull(token, AssertMessage.NOT_NULL_PARAM);
        Assert.notNull(secret, AssertMessage.NOT_NULL_PARAM);
        // secret key
        byte[] bytes = secret.getBytes();
        SecretKey secretKey = new SecretKeySpec(bytes, 0, bytes.length, SignatureAlgorithm.HS256.getJcaName());
        // parser token
        return Jwts.parser().setAllowedClockSkewSeconds(15).setSigningKey(secretKey).parseClaimsJws(token).getBody();
    }
}
